#include "AbstractManage.h"

#include <QtConcurrent>

AbstractManage::AbstractManage(const int &handleMaxThreadCount, QObject * parent) : QObject(parent)
{
	handleThreadPool_.reset(new QThreadPool);
	serverThreadPool_.reset(new QThreadPool);

	handleThreadPool_->setMaxThreadCount(handleMaxThreadCount);
	serverThreadPool_->setMaxThreadCount(1);
}

AbstractManage::~AbstractManage()
{
	this->stopHandleThread();
}

bool AbstractManage::begin()
{
	if (QThread::currentThread() != this->thread())
	{
		qDebug() << "JQHttpServer::Manage::listen: error: listen from other thread";
		return false;
	}

	if (this->isRunning())
	{
		qDebug() << "JQHttpServer::Manage::close: error: already running";
		return false;
	}

	return this->startServerThread();
}

void AbstractManage::close()
{
	if (!this->isRunning())
	{
		qDebug() << "JQHttpServer::Manage::close: error: not running";
		return;
	}

	emit readyToClose();

	if (serverThreadPool_->activeThreadCount())
	{
		this->stopServerThread();
	}
}

bool AbstractManage::startServerThread()
{
	QSemaphore semaphore;

	QtConcurrent::run(serverThreadPool_.data(), [&semaphore, this]()
	{
		QEventLoop eventLoop;
		QObject::connect(this, &AbstractManage::readyToClose, &eventLoop, &QEventLoop::quit);

		if (!this->onStart())
		{
			semaphore.release(1);
		}

		semaphore.release(1);

		eventLoop.exec();

		this->onFinish();
	});

	semaphore.acquire(1);

	return this->isRunning();
}

void AbstractManage::stopHandleThread()
{
	handleThreadPool_->waitForDone();
}

void AbstractManage::stopServerThread()
{
	serverThreadPool_->waitForDone();
}

void AbstractManage::newSession(const QPointer< Session > &session)
{
	//    qDebug() << "newConnection:" << session.data();

	session->setHandleAcceptedCallback([this](const QPointer< Session > &session){ this->handleAccepted(session); });

	auto session_ = session.data();
	connect(session.data(), &QObject::destroyed, [this, session_]()
	{
        //qDebug() << "disConnection:" << session;

		this->mutex_.lock();
		this->availableSessions_.remove(session_);
		this->mutex_.unlock();
	});
	availableSessions_.insert(session.data());
}

void AbstractManage::handleAccepted(const QPointer<Session> &session)
{
	QtConcurrent::run(handleThreadPool_.data(), [this, session]()
	{
		if (!this->httpAcceptedCallback_)
		{
			qDebug() << "JQHttpServer::Manage::handleAccepted: error, httpAcceptedCallback_ is nullptr";
			return;
		}

		this->httpAcceptedCallback_(session);
	});
}
